package translinkApp.Activities;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import translinkApp.Data.Utils.Functions;
import translinkApp.Data.xmlparse.StationsHandler;
import translinkApp.Data.xmlparse.StationsHandler.Station;
import translinkApp.DataTypes.QuickAction.ActionItem;
import translinkApp.DataTypes.QuickAction.QuickAction;
import translinkApp.views.map.TransMapOverlay;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MapView.LayoutParams;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.lach.common.ErrorObject;
import com.lach.common.ProgressAsyncTask;

public class MapViewActivity extends MapActivity {

	private MapView mapView;
	private TextView addressText;
	private MapController mc;
	private GeoPoint pinnedLocation;
	private String currentAddress = "";
	private MyLocationOverlay myLoc;
	private TransMapOverlay mapOverlay;
	private Button stationsButton;

	public String getCurrentAddress() {
		return currentAddress;
	}

	public void setCurrentAddress(String currentAddress) {
		this.currentAddress = currentAddress;
	}

	public MapView getMapView() {
		return mapView;
	}

	public void setMapView(MapView mapView) {
		this.mapView = mapView;
	}

	public String getAddressText() {
		return addressText.getText().toString();
	}

	public void setAddressText(String addressText) {
		this.addressText.setText(addressText);
	}

	public MapController getMapController() {
		return mc;
	}

	public void setMc(MapController mc) {
		this.mc = mc;
	}

	public GeoPoint getPinnedLocation() {
		return pinnedLocation;
	}

	public void setPinnedLocation(GeoPoint pinnedLocation) {
		this.pinnedLocation = pinnedLocation;
	}

	public MyLocationOverlay getMyLoc() {
		return myLoc;
	}

	public void setMyLoc(MyLocationOverlay myLoc) {
		this.myLoc = myLoc;
	}

	public TransMapOverlay getMapOverlay() {
		return mapOverlay;
	}

	public void setMapOverlay(TransMapOverlay mapOverlay) {
		this.mapOverlay = mapOverlay;
	}

	public Address getAddress(GeoPoint p) {

		Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
		try {
			if (geoCoder != null) {
				List<Address> addresses = geoCoder.getFromLocation(p.getLatitudeE6() / 1E6,
						p.getLongitudeE6() / 1E6, 1);

				if (addresses != null) {
					if (addresses.size() > 0) {
						return addresses.get(0);
					}

				}
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	private boolean goToAddress(String name, boolean suburb, boolean changeText) {
		Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
		try {

			if (suburb) {
				name = RemoveSuburbInfo(name);
			}
			name = name + " Australia";

			List<Address> addresses = geoCoder.getFromLocationName(name, 5);

			if (addresses.size() > 0) {
				pinnedLocation = new GeoPoint((int) (addresses.get(0).getLatitude() * 1E6),
						(int) (addresses.get(0).getLongitude() * 1E6));
				mc.animateTo(pinnedLocation);
				mapView.invalidate();
			}

			if (pinnedLocation == null) {
				if (name.equals("") == false) {
					String[] locations = name.split(" ");

					String newLocation = "";
					for (int i = 0; i < locations.length - 2; i++) {
						newLocation += locations[i] + " ";
					}
					newLocation = newLocation.trim();

					return goToAddress(newLocation, suburb, changeText);
				}
				return false;
			}

			getAddress(pinnedLocation);

			Toast.makeText(getBaseContext(), name, Toast.LENGTH_SHORT).show();

			if (changeText) {
				addressText.setText(name);
			}

			return true;

		} catch (IOException e) {

		}
		return false;
	}

	private String RemoveSuburbInfo(String data) {

		data = data.replace(" (Suburb)", "");
		data = data.replace(" (Location)", "");
		data = data.replace(" (Landmark)", "");
		data = data.replace(" (Stop)", "");
		return data;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void onCreate(Bundle icicle) {

		super.onCreate(icicle);
		setContentView(R.layout.mapview);

		Intent startingIntent = getIntent();
		Bundle extras = startingIntent.getExtras();
		String lastLocation = extras.getString("location");

		mapView = (MapView) findViewById(R.id.mapView);
		addressText = (TextView) findViewById(R.id.mapViewAddress);
		addressText.setText("");
		LinearLayout zoomLayout = (LinearLayout) findViewById(R.id.zoom);
		View zoomView = mapView.getZoomControls();

		zoomLayout.addView(zoomView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT));
		mapView.displayZoomControls(true);

		mc = mapView.getController();

		// ---Add a location marker--

		boolean locationSelected = false;
		if (lastLocation != null) {
			if (lastLocation.equals("") == false) {
				if (goToAddress(lastLocation, false, true)) {
					mc.setZoom(15);
					currentAddress = lastLocation;
					locationSelected = true;
				}
			}
		}

		Drawable drawable = getResources().getDrawable(R.drawable.marker_default);
		mapOverlay = new TransMapOverlay(drawable, this,
				new TransMapOverlay.OverlaySelectedListener() {

					@Override
					public void onOverlaySelected(OverlayItem item) {
						currentAddress = item.getTitle();
						finishActivity(false);
					}
				});
		List<Overlay> listOfOverlays = mapView.getOverlays();
		listOfOverlays.clear();
		listOfOverlays.add(mapOverlay);

		myLoc = new MyLocationOverlay(this, mapView);
		myLoc.enableMyLocation();
		listOfOverlays.add(myLoc);

		if (!locationSelected) {
			myLoc.runOnFirstFix(new Runnable() {
				public void run() {
					mc.animateTo(myLoc.getMyLocation());
				}
			});
		}

		mc.setZoom(15);
		mapView.invalidate();

		Button selectStreet = (Button) findViewById(R.id.selectStreetButton);
		selectStreet.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				finishActivity(true);
			}
		});

		Button myLocationButton = (Button) findViewById(R.id.mapMyLocationButton);
		myLocationButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
				mc.animateTo(myLoc.getMyLocation());
				} catch (Exception e) {
					
				}
			}
		});

		stationsButton = (Button) findViewById(R.id.mapStationsButton);
		stationsButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				getLocalStations();
			}
		});

	}

	@Override
	protected void onResume() {
		if (myLoc != null) {
			myLoc.enableMyLocation();

		}
		super.onResume();
	}

	@Override
	protected void onPause() {
		if (myLoc != null) {
			myLoc.disableMyLocation();

		}
		super.onPause();

	}

	@Override
	protected boolean isRouteDisplayed() {

		return false;
	}

	public static final String MapResultStringKey = "MapResult";
	public static final String MapResultStreetStringKey = "MapType";

	private void finishActivity(boolean isStreet) {

		Intent result = new Intent();

		result.putExtra(MapResultStringKey, currentAddress);
		result.putExtra(MapResultStreetStringKey, isStreet);
		setResult(Activity.RESULT_OK, result);

		finish();

	}

	private void getLocalStations() {
		if (getMapView().getZoomLevel() <= 15) {
			Toast.makeText(this, "You must zoom in more to use this function", Toast.LENGTH_SHORT)
					.show();

			return;
		}
		
//		PopupMenu menu = new PopupMenu(this, stationsButton);
//		menu.getMenuInflater().inflate(R.menu.stationmenu, menu.getMenu());
//		menu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
//			
//			@Override
//			public boolean onMenuItemClick(MenuItem item) {
//				
//				return true;
//			}
//		});
		
        ActionItem addAction = new ActionItem();

		addAction.setTitle("Train Stops");
//		addAction.setIcon(getResources().getDrawable(R.drawable.ic_add));

		//Accept action item
		ActionItem accAction = new ActionItem();

		accAction.setTitle("Bus Stops");
		accAction.setIcon(getResources().getDrawable(R.drawable.ic_bus));

		//Upload action item
		ActionItem upAction = new ActionItem();

		upAction.setTitle("Train & Bus\nStops");
//		upAction.setIcon(getResources().getDrawable(R.drawable.ic_up));

		final QuickAction mQuickAction 	= new QuickAction(this);

		mQuickAction.addActionItem(addAction);
		mQuickAction.addActionItem(accAction);
		mQuickAction.addActionItem(upAction);

		//setup the action item click listener
		mQuickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {			
			@Override
			public void onItemClick(int pos) {

				if (pos == 0) {
					new GetStationPoints(MapViewActivity.this, false, true).execute();
				} else if (pos == 1) {
					new GetStationPoints(MapViewActivity.this, true, false).execute();
				} else if (pos == 2) {
					new GetStationPoints(MapViewActivity.this, true, true).execute();
				}	
			}
		});
		mQuickAction.animateTrack(false);
		mQuickAction.show(stationsButton);

	}

	private class GetStationPoints extends ProgressAsyncTask<ArrayList<Station>> {

		private final boolean bus;
		private final boolean train;

		public GetStationPoints(Context c, boolean bus, boolean train) {
			super(c, "Please wait...", "Loading stations");
			this.bus = bus;
			this.train = train;

		}

		protected ErrorObject<ArrayList<Station>> doInBackground(String... params) {
			ErrorObject<ArrayList<Station>> contacts = new ErrorObject<ArrayList<Station>>();

			try {
				GeoPoint startPoint = mapView.getProjection().fromPixels(0, 0);
				GeoPoint endPoint = mapView.getProjection().fromPixels(mapView.getWidth(),
						mapView.getHeight());

				// SharedPreferences prefs = PreferenceManager
				// .getDefaultSharedPreferences(getBaseContext());
				// String stationurl = prefs.getString("stationurl", "");

				String url = String
						.format("http://122.248.235.212/TranslinkKiller-0.1/station/getStationsInSquare?lat1=%s&long1=%s&lat2=%s&long2=%s",
								startPoint.getLatitudeE6() / 1E6,
								startPoint.getLongitudeE6() / 1E6, endPoint.getLatitudeE6() / 1E6,
								endPoint.getLongitudeE6() / 1E6);
				
				if (bus) {
					url += "&stationtype=bus";
				}

				if (train) {
					url += "&stationtype=train";
				}

				InputStream urlSource = Functions.getUrlStream(url);
				InputSource source = new InputSource(urlSource);
				SAXParserFactory factory = SAXParserFactory.newInstance();

				// create a parser
				SAXParser parser = factory.newSAXParser();

				// create the reader (scanner)
				XMLReader xmlreader = parser.getXMLReader();

				// instantiate our handler
				StationsHandler fh = new StationsHandler();

				// assign our handler
				xmlreader.setContentHandler(fh);

				// perform the synchronous parse
				xmlreader.parse(source);

				// should be done... let's display our results
				contacts.setItem(fh.getStations());

			} catch (Exception e) {
				contacts.setException(e);
			}

			return contacts;

		}

		protected void onPostExecute(ErrorObject<ArrayList<Station>> result) {
			super.onPostExecute(result);

			mapOverlay.clearOverlay();

			if (result.getItem() != null) {
				for (Station s : result.getItem()) {
					OverlayItem overlayitem = new OverlayItem(new GeoPoint(
							(int) (s.latitude * 1E6), (int) (s.longitude * 1E6)), s.description,
							s.description);
					mapOverlay.addOverlay(overlayitem);

				}
			} else {
				Toast.makeText(MapViewActivity.this,
						"Could not find stations. The url may be broken", Toast.LENGTH_SHORT)
						.show();
			}
		}
	}

}